#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
语音合成服务
基于讯飞WebSocket流式语音合成API
"""

import websocket
import datetime
import hashlib
import base64
import hmac
import json
import logging
import os
import ssl
import threading
import time
from urllib.parse import urlencode
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class TTSWebSocketParam:
    """语音合成WebSocket参数类"""
    
    def __init__(self, app_id, api_key, api_secret, text, voice="xiaoyan", 
                 audio_format="raw", sample_rate="16000", speed=50, volume=50, pitch=50):
        self.app_id = app_id
        self.api_key = api_key
        self.api_secret = api_secret
        self.text = text
        
        # 公共参数
        self.common_args = {"app_id": self.app_id}
        
        # 业务参数
        self.business_args = {
            "aue": audio_format,  # 音频编码
            "auf": f"audio/L16;rate={sample_rate}",  # 音频采样率
            "vcn": voice,  # 发音人
            "tte": "utf8",  # 文本编码格式
            "speed": speed,  # 语速
            "volume": volume,  # 音量
            "pitch": pitch,  # 音高
            "bgs": 0,  # 背景音
            "reg": "0",  # 英文发音方式
            "rdn": "0"  # 数字发音方式
        }
        
        # 数据参数
        self.data = {
            "status": 2,  # 数据状态，固定为2
            "text": str(base64.b64encode(self.text.encode('utf-8')), "UTF8")
        }
    
    def create_url(self):
        """生成WebSocket连接URL"""
        url = 'wss://tts-api.xfyun.cn/v2/tts'
        
        # 生成RFC1123格式的时间戳
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))
        
        # 拼接签名字符串
        signature_origin = "host: " + "tts-api.xfyun.cn" + "\n"
        signature_origin += "date: " + date + "\n"
        signature_origin += "GET " + "/v2/tts " + "HTTP/1.1"
        
        # 进行hmac-sha256加密
        signature_sha = hmac.new(
            self.api_secret.encode('utf-8'), 
            signature_origin.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()
        signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
        
        # 构建authorization
        authorization_origin = 'api_key="%s", algorithm="%s", headers="%s", signature="%s"' % (
            self.api_key, "hmac-sha256", "host date request-line", signature_sha)
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
        
        # 拼接鉴权参数
        v = {
            "authorization": authorization,
            "date": date,
            "host": "tts-api.xfyun.cn"
        }
        
        # 生成完整URL
        url = url + '?' + urlencode(v)
        return url


class TTSService:
    """语音合成服务"""
    
    def __init__(self, app_id, api_key, api_secret):
        self.app_id = app_id
        self.api_key = api_key
        self.api_secret = api_secret
        self.audio_data = b""
        self.is_completed = False
        self.error_message = None
        self.ws = None
        
        logger.info("语音合成服务初始化完成")
    
    def _on_message(self, ws, message):
        """处理WebSocket消息"""
        try:
            message_data = json.loads(message)
            code = message_data.get("code", -1)
            sid = message_data.get("sid", "")
            
            if code != 0:
                error_msg = message_data.get("message", "未知错误")
                logger.error(f"语音合成错误: {error_msg}")
                self.error_message = f"语音合成失败: {error_msg}"
                self.is_completed = True
                return
            
            # 处理音频数据
            data = message_data.get("data", {})
            if data:
                audio_base64 = data.get("audio", "")
                status = data.get("status", 0)
                
                if audio_base64:
                    # 解码音频数据
                    audio_bytes = base64.b64decode(audio_base64)
                    self.audio_data += audio_bytes
                    logger.info(f"接收到音频数据: {len(audio_bytes)} 字节")
                
                # 检查是否合成完成
                if status == 2:
                    logger.info("语音合成完成")
                    self.is_completed = True
                    ws.close()
            
        except Exception as e:
            logger.error(f"处理消息异常: {e}")
            self.error_message = f"处理消息异常: {e}"
            self.is_completed = True
    
    def _on_error(self, ws, error):
        """处理WebSocket错误"""
        logger.error(f"WebSocket错误: {error}")
        self.error_message = f"WebSocket错误: {error}"
        self.is_completed = True
    
    def _on_close(self, ws, *args):
        """处理WebSocket关闭"""
        logger.info("WebSocket连接已关闭")
        self.is_completed = True
    
    def _on_open(self, ws):
        """处理WebSocket连接建立"""
        def run():
            # 构建请求数据
            request_data = {
                "common": self.ws_param.common_args,
                "business": self.ws_param.business_args,
                "data": self.ws_param.data
            }
            
            request_json = json.dumps(request_data)
            logger.info("开始发送文本数据进行语音合成")
            ws.send(request_json)
        
        # 在新线程中发送数据
        threading.Thread(target=run).start()
    
    def synthesize(self, text, output_file=None, voice="xiaoyan", 
                   audio_format="raw", sample_rate="16000", 
                   speed=50, volume=50, pitch=50):
        """
        语音合成
        
        Args:
            text: 要合成的文本
            output_file: 输出文件路径（可选）
            voice: 发音人
            audio_format: 音频格式
            sample_rate: 采样率
            speed: 语速
            volume: 音量
            pitch: 音高
            
        Returns:
            bytes: 合成的音频数据
        """
        logger.info(f"开始语音合成: {text[:50]}...")
        
        # 重置状态
        self.audio_data = b""
        self.is_completed = False
        self.error_message = None
        
        # 创建WebSocket参数
        self.ws_param = TTSWebSocketParam(
            app_id=self.app_id,
            api_key=self.api_key,
            api_secret=self.api_secret,
            text=text,
            voice=voice,
            audio_format=audio_format,
            sample_rate=sample_rate,
            speed=speed,
            volume=volume,
            pitch=pitch
        )
        
        # 生成WebSocket URL
        ws_url = self.ws_param.create_url()
        
        try:
            # 创建WebSocket连接
            websocket.enableTrace(False)
            self.ws = websocket.WebSocketApp(
                ws_url,
                on_message=self._on_message,
                on_error=self._on_error,
                on_close=self._on_close,
                on_open=self._on_open
            )
            
            # 运行WebSocket连接
            self.ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
            
            # 检查是否有错误
            if self.error_message:
                raise Exception(self.error_message)
            
            # 保存音频文件（如果指定了输出文件）
            if output_file and self.audio_data:
                with open(output_file, 'wb') as f:
                    f.write(self.audio_data)
                logger.info(f"音频文件已保存: {output_file}")
            
            logger.info(f"语音合成完成，音频大小: {len(self.audio_data)} 字节")
            return self.audio_data
            
        except Exception as e:
            logger.error(f"语音合成失败: {e}")
            raise Exception(f"语音合成失败: {e}")
    
    def synthesize_to_file(self, text, output_file, **kwargs):
        """
        语音合成并保存到文件
        
        Args:
            text: 要合成的文本
            output_file: 输出文件路径
            **kwargs: 其他参数
        """
        return self.synthesize(text, output_file=output_file, **kwargs)


def main():
    """测试函数"""
    print("=== 语音合成服务测试 ===")
    
    # 从配置文件加载配置
    with open('config.json', 'r', encoding='utf-8') as f:
        config = json.load(f)
    
    # 创建语音合成服务
    tts_config = config['text_to_speech']
    tts_service = TTSService(
        app_id=tts_config['app_id'],
        api_key=tts_config['api_key'],
        api_secret=tts_config['api_secret']
    )
    
    # 测试文本
    test_texts = [
        "你好，我是讯飞语音合成服务",
        "今天天气真不错",
        "人工智能技术正在快速发展"
    ]
    
    for i, text in enumerate(test_texts, 1):
        print(f"\n--- 测试 {i} ---")
        print(f"文本: {text}")
        
        try:
            # 合成语音
            output_file = f"test_tts_{i}.pcm"
            audio_data = tts_service.synthesize_to_file(
                text=text,
                output_file=output_file,
                voice="xiaoyan",
                speed=50,
                volume=50,
                pitch=50
            )
            
            print(f"合成成功，音频大小: {len(audio_data)} 字节")
            print(f"音频文件: {output_file}")
            
        except Exception as e:
            print(f"合成失败: {e}")


if __name__ == "__main__":
    main()
